using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using NETL.Engine.Data;
using NETL.Engine.Util;

namespace NETL.Engine.Source
{
	public class BasicFileSource : MessageSourceBase
	{
		private TimeSpan myPollInterval = new TimeSpan(0, 1, 0);
		private string myFileMask;
		private string myPath;
		private Timer myTimer;

		public TimeSpan PollInterval
		{
			get { return myPollInterval; }
			set { myPollInterval = value; }
		}

		public string FileMask
		{
			get { return myFileMask; }
			set { myFileMask = value; }
		}

		public string Path
		{
			get { return myPath; }
			set { myPath = value; }
		}

		public override void Stop()
		{
			if (Logger.IsDebugEnabled)
			{
				Logger.DebugFormat("Stopping {0}", Name);
			}

			myTimer.Dispose();

			OnStopped();
		}

		public override void Start()
		{
			if (Logger.IsDebugEnabled)
			{
				Logger.DebugFormat("Starting {0}", Name);
			}

			myTimer = new Timer(new TimerCallback(Read));
			myTimer.Change(new TimeSpan(0), myPollInterval);

			OnStarted();
		}

		public override ExecutionResult Test()
		{
			if (myPath == null)
			{
				string message = String.Format("Path is not set.");
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration, message);
			}
			if (myFileMask == null)
			{
				string message = String.Format("File mask \"{0}\" is invalid.", myPath);
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration, message);
			}
			if (myPollInterval == null || myPollInterval.TotalSeconds == 0)
			{
				string message = String.Format("PollInterval \"{0}\" must be > 0 seconds.", myPath);
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration, message);
			}

			DirectoryInfo info = new DirectoryInfo(myPath);

			if (!info.Exists)
			{
				string message = String.Format("Path \"{0}\" is not accessible.", myPath);
				return new ExecutionResult(ExecutionStatus.InvalidConfiguration, message);
			}
			
			return new ExecutionResult(ExecutionStatus.Success);
		}

		public void Read()
		{
			try
			{
				DirectoryInfo directoryInfo = new DirectoryInfo(FileUtil.AbsolutePath(myPath));

				foreach (FileInfo fi in directoryInfo.GetFiles(myFileMask))
				{
					try
					{
						using (StreamReader reader = fi.OpenText())
						{
							string data = reader.ReadToEnd();
							TextMessage msg = new TextMessage(fi.Name, data);
							OnReceived(msg);
						}
					}
					catch (Exception e)
					{
						ExecutionResult res = new ExecutionResult(ExecutionStatus.Failure,
							String.Format("Failed to read from file \"{0}\".", fi.FullName), e);
						OnError(res);
					}
				}
			}
			catch (Exception ex)
			{
				ExecutionResult res = new ExecutionResult(ExecutionStatus.Failure, "Failed to fetch file(s) from directory.", ex);
				OnError(res);
			}
		}

		protected void Read(Object stateInfo)
		{
			Read();
		}

	}
}
